#include <stdio.h>

#include "anora.h"

#include "stringparsing/stringparser.h"

int
roll_dice_parse_str( const char * psz_str, unsigned int * nd, int * dp, int * md )
{
	std::string str(psz_str);
	unsigned int num_d = StringParser::getOccurrencesInString( 'd', str );
	if( !num_d )
	{
		return -1;
	}
	unsigned int ndc = 1;
	int t = 0;
	int mod = 0;
	std::string first = str.substr( 0, str.find_first_of( 'd' ) );
	str = str.substr( str.find_first_of( 'd' ) + 1 );
	std::string mid = str;
	int pm = 0;
	if( StringParser::getOccurrencesInString( '+', str ) )
	{
		pm = 1;
		mid = str.substr( 0, str.find_last_of( '+' ) );
	}
	else
	if( (pm = StringParser::getOccurrencesInString( '-', str )) )
	{
		if( pm == 2 )
		{
			mid = str.substr( 0, str.find_last_of( '-' ) );
		}
		pm = -1;
	}
	if( pm )
	{
		std::string last = str.substr( str.find_last_of( pm < 0 ? '-' : '+' ) + ( pm > 0 ? 1 : 0 ) );
		sscanf( last.c_str(), "%d", &mod );
	}
	sscanf( mid.c_str(), "%d", &t );
	if( first.length() )
		sscanf( first.c_str(), "%u", &ndc );
	if( nd )
		*nd = ndc;
	if( dp )
		*dp = t;
	if( md )
		*md = mod;
	return 0;
}

int
roll_dice_str( const char * psz_str )
{
	unsigned int nd = 1;
	int t = 0;
	int mod = 0;
	int err = 0;
	if( (err = roll_dice_parse_str( psz_str, &nd, &t, &mod )) )
	{
		throw err;
	}
	return roll_dice( nd, t, mod );
}

int
roll_multidice_str( const char * psz_str, int sign )
{
	std::string str(psz_str);
	unsigned int num_d = StringParser::getOccurrencesInString( 'd', str );
	if( !num_d )
	{
		throw -1;
		//return -1;
	}
	unsigned int ndc = 1;
	int t = 0;
	int mod = 0;
	std::string first = str.substr( 0, str.find_first_of( 'd' ) );
	str = str.substr( str.find_first_of( 'd' ) + 1 );
	std::string mid = str;
	int pm = 0;
	if( mid[0] == '-' )
	{
		pm = -1;
		mid = mid.substr( 1 );
	}
	else
		pm = 1;
	unsigned int plusindex = mid.find_first_of('+');
	unsigned int minusindex = mid.find_first_of('-');
	std::string last;
	int pm2 = 0;
	if( plusindex != (unsigned int)std::string::npos && minusindex != (unsigned int)std::string::npos )
	{
		if( plusindex < minusindex )
		{
			last = mid.substr( plusindex+1 );
			mid = mid.substr( 0, plusindex );
			pm2 = 1;
		}
		else
		{
			last = mid.substr( minusindex+1 );
			mid = mid.substr( 0, minusindex );
			pm2 = -1;
		}
	}
	else
	if( plusindex != (unsigned int)std::string::npos && minusindex == (unsigned int)std::string::npos )
	{
		last = mid.substr( plusindex+1 );
		mid = mid.substr( 0, plusindex );
		pm2 = 1;
	}
	else
	if( plusindex == (unsigned int)std::string::npos && minusindex != (unsigned int)std::string::npos )
	{
		last = mid.substr( minusindex+1 );
		mid = mid.substr( 0, minusindex );
		pm2 = -1;
	}
	else
	{

	}
	//std::cout << "First='"+first+"', Mid='"+mid+"', Last='"+last+"'" << std::endl;
	if( first.length() )
		sscanf( first.c_str(), "%d", &ndc );
	if( !mid.length() )
		throw -2;
	sscanf( mid.c_str(), "%d", &t );
	t *= pm;
	unsigned int nd = ndc;
	int dp = t;
	int md = mod;
	if( last.length() )
	{
		unsigned int num_d2 = StringParser::getOccurrencesInString( 'd', last );
		if( num_d2 )
		{
			return roll_dice( nd, dp, 0 ) + roll_multidice_str( last.c_str(), sign * pm2 ) * pm2;
		}
		sscanf( last.c_str(), "%d", &md );
	}
	return roll_dice( nd, dp, md * sign );
}


inline
int
roll_single_die( int dice_Power )
{
	return ( rand() % dice_Power ) + 1;
}

/*Dice roll equation.
Precondition: Enter 3 values, XYZ, where the equation is XdY + Z. Example 2d10 + 5. Randomizer is already initialized.
X must be a positive value.=
Y may be negative.
Z may be negative.
Postcondition: Returns the total rolled value, or throws -1 on error.
*/
int
roll_dice( unsigned int num_Dice, int dice_Power, int modifier )
{
	//Make sure you have at least one dice being rolled.
	if( num_Dice <= 0 || (dice_Power <= 1 && dice_Power >= -1) )
	{
		throw -1;
		return 0;
	}

	int total = 0; //Amount from the roll totaled.
	unsigned int run_Count; //How many times the program has rolled.

	int multmod = ( dice_Power < 0 ? -1 : 1 );
	dice_Power *= multmod;

	//For statement to roll the dice a set amount of times.
	for(run_Count = 0; run_Count < num_Dice; ++run_Count)
	{
		total += roll_single_die( dice_Power ) * multmod;
	}
	return (total + modifier);
}

